<?php
/**
 * Created by 柚子i.
 * User: Emperor
 * Date: 2019/6/26
 * Time: 20:37
 */

namespace app\common\service\control;


use app\common\service\airquality\AqiService;
use app\common\service\BaseService;
use app\common\service\companyIndustry\tsinghua\TsinghuaEmissionService;
use app\common\service\ControlEmissionService;
use app\common\service\EmissionService;
use app\common\service\FormulaService;
use think\Db;

/**
 * Class ControlPlanConfirm
 * @package app\common\service\control
 * 1.confirmPlanConclusion          提交方案结论
 * 2.getControlEffect               站点管控效果数据
 * 3.getStationTrackTrendChartData  获取站点6参预报值、推演值、实测值数据
 * 4.getStationTrackData            获取站点管控跟踪数据
 * 5.confirmPlanBeLaidUp            提交方案
 * 6.updateConfirmPlan              更新方案数据
 * 7.getPlanSummaryAll              获取全部方案推演数据
 * 8.getStationAverageDeduction     获取推演改善值
 * 9.getStationAveragePollutant     获取站点污染物平均下降浓度
 * 10.getStationAverageAqi          获取全市减排后AQI均值
 * 11.getStationForecastAverageAqi  获取预报值AQI
 * 12.getForecastAqi                计算预报值AQI
 * 13.getForecastData               获取全市预报值
 * 14.getDeductionAqi               获取全市推演3天AQI平均值
 * 15.getDeductionData              获取3天推演数据
 * 16.getPlanIdByPlanNumber         根据预案编号获取方案id列表
 */
class ControlPlanConfirm extends BaseService
{
    public function confirmPlanConclusion()
    {

    }

    /**
     * Notes :站点管控效果数据
     * @param $paramArr
     * @return array
     * @throws \Exception
     * @author lichao   2019/7/1
     */
    public function getControlEffect($paramArr)
    {
        try {
            $control          = new ControlPlan();
            $programmeNumber  = $paramArr['plan_number'];
            $planId           = $this->getPlanIdByPlanNumber($paramArr['plan_number'], '', true);
            $planData         = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
            $publishTime      = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
            $controlStartTime = $planData['control_start_time'];
            $controlEndTime   = $planData['control_end_time'];
            $stationList      = $control->getStationList(53, 1);
            $dateRange        = getDateFromRange($controlStartTime, $controlEndTime);
            $dayNum           = count($dateRange);

            // 站点预报值
            $stationForecastData = $control->getStationForecastData($stationList, $dayNum, $publishTime, $controlStartTime, $controlEndTime);
            // 站点推演值
            $stationDeductionData = $control->getStationDeductionData($stationList, $dayNum, $programmeNumber, $planId, $publishTime, $controlStartTime, $controlEndTime);

            // 获取站点实测值
            $stationRealtimeData = $control->getStationRealtimeData($controlStartTime, $controlEndTime);

            $aqi              = new AqiService();
            $newData          = array();
            $pollutantsKeyArr = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'aqi'
            ];
            $aqiKeyArr        = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'o3_8h'
            ];

            foreach ($stationList as $station => $stationName) {
                $forecast_cp_arr  = array();
                $deduction_cp_arr = array();
                $realtime_cp_arr  = array();
                foreach ($aqiKeyArr as $pollutantVal) {
                    $pollutantKey = $pollutantVal . "_" . $station;
                    if ($pollutantVal == 'o3' || $pollutantVal == 'o3_8h') {
                        $forecast_cp_arr[$pollutantVal . '_average_max']  = $stationForecastData[$pollutantKey];
                        $deduction_cp_arr[$pollutantVal . '_average_max'] = $stationDeductionData[$pollutantKey];
                        // 实测数据
                        if (!empty($stationRealtimeData)) {
                            $realPollutantVal = $stationRealtimeData[$station][$pollutantVal];

                            $realtime_cp_arr[$pollutantVal . '_average_max'] = $realPollutantVal;
                        }
                    } else {
                        $forecast_cp_arr[$pollutantVal . '_average']  = $stationForecastData[$pollutantKey];
                        $deduction_cp_arr[$pollutantVal . '_average'] = $stationDeductionData[$pollutantKey];
                        // 实测数据
                        if (!empty($stationRealtimeData)) {
                            $realPollutantVal = $stationRealtimeData[$station][$pollutantVal];

                            $realtime_cp_arr[$pollutantVal . '_average'] = $realPollutantVal;
                        }
                    }
                }
                // 计算AQI
                $stationForecastAqi                      = $aqi->getAqi($forecast_cp_arr)['aqi'];
                $stationDeductionAqi                     = $aqi->getAqi($deduction_cp_arr)['aqi'];
                $stationForecastData['aqi_' . $station]  = $stationForecastAqi;
                $stationDeductionData['aqi_' . $station] = $stationDeductionAqi;
                // 实测值AQI
                if (!empty($stationRealtimeData)) {
                    $stationRealtimeAqi                   = $aqi->getAqi($realtime_cp_arr)['aqi'];
                    $stationRealtimeData[$station]['aqi'] = $stationRealtimeAqi;
                }

                foreach ($pollutantsKeyArr as $item) {
                    $pollutants   = $item == 'pm25' ? 'PM2_5' : strtoupper($item);
                    $pollutant    = $item == 'pm25' ? 'PM2.5' : strtoupper($item);
                    $pollutantKey = $item . "_" . $station;
                    if (isset($stationForecastData[$pollutantKey])) {
                        $forecastPollutantVal  = $stationForecastData[$pollutantKey];
                        $deductionPollutantVal = $stationDeductionData[$pollutantKey];
                        $improve               = $forecastPollutantVal - $stationRealtimeData[$station][$item];
                        $forecastValue         = $control->roundStationValue($forecastPollutantVal, $item);
                        $deductionValue        = $control->roundStationValue($deductionPollutantVal, $item);
                        // 组合数组
                        $newData[$pollutants][$station]['station_id'] = $station;
                        $newData[$pollutants][$station]['site']       = $stationName;
                        $newData[$pollutants][$station]['pollutants'] = $pollutant;
                        $newData[$pollutants][$station]['forecast']   = $forecastValue;
                        $newData[$pollutants][$station]['deduction']  = $deductionValue;
                        $newData[$pollutants][$station]['improve']    = round($improve, 1);
                        // 站点实测值
                        if (!empty($stationRealtimeData)) {
                            foreach ($stationRealtimeData as $stationKey => $realtimeDatum) {
                                if ($stationKey == $station) {
                                    $realtimeValue = $control->roundStationValue($realtimeDatum[$item], $item);

                                    $newData[$pollutants][$station]['realtime'] = $realtimeValue;
                                }
                            }
                        } else {
                            $newData[$pollutants][$station]['realtime'] = '';
                        }
                    }
                }
            }

            $data = array();
            if (!empty($newData)) {
                foreach ($newData as $i => $newDatum) {
                    $data[$i] = array_values($newDatum);
                    $dataSum  = array();
                    foreach ($newDatum as $j => $item) {
                        if ($j != 0) {
                            array_push($dataSum, $item['improve']);
                        }
                    }
                    $data[$i . 'average'] = round(array_sum($dataSum) / 5, 1);
                }
            } else {
                return array([[], [], []]);
            }

            return $data;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :获取站点6参预报值、推演值、实测值数据
     * @param $paramArr
     * @return array
     * @throws \Exception
     * @author lichao   2019/6/29
     */
    public function getStationTrackTrendChartData($paramArr)
    {
        try {
            $control         = new ControlPlan();
            $programmeNumber = $paramArr['plan_number'];
            $planId          = $this->getPlanIdByPlanNumber($paramArr['plan_number'], '', true);
            $planData        = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
            $publishTime     = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
            // $planPublishTime = date("Y-m-d 19:00:00", strtotime($publishTime));
            $controlStartTime = $planData['control_start_time'];
            $controlEndTime   = $planData['control_end_time'];
            $stationId        = $paramArr['station_id'];
            $pollutant        = $paramArr['pollutant'];
            $dateRange        = getDateFromRange($controlStartTime, $controlEndTime, true);

            // 获取站点预报值
            $stationForecastSql  = "SELECT * FROM `air_quality_station_aqi_forecast_hour` WHERE `region_id` = 53 AND 
`station_id` = ? AND `publish_time` = ? AND `predict_time` between ? AND ?";
            $stationForecastData = Db::query($stationForecastSql, array(
                $stationId, $publishTime, $controlStartTime, $controlEndTime));
            $forecastPollutant   = array_column($stationForecastData, $pollutant);

            // 获取站点实测值
            $stationRealtimeSql  = "SELECT * FROM `air_quality_station_aqi_realtime_hour` WHERE `region_id` = 53 AND 
`station_id` = ? AND `publish_time` between ? AND ?";
            $stationRealtimeData = Db::query($stationRealtimeSql, array(
                $stationId, $controlStartTime, $controlEndTime));
            $realtimeArr         = array();
            $realtimePollutant   = array();
            foreach ($stationRealtimeData as $stationRealtimeDatum) {
                $realtimeArr[$stationRealtimeDatum['publish_time']] = $stationRealtimeDatum[$pollutant];
            }
            foreach ($dateRange as $key => $item) {
                $dateFormat = date("Y-m-d H:i:s", strtotime($item));
                if (isset($realtimeArr[$dateFormat])) {
                    $realtimePollutant[$dateFormat] = $realtimeArr[$dateFormat];
                } else {
                    $realtimePollutant[$dateFormat] = '-';
                }
            }

            $realtimePollutant = array_values($realtimePollutant);

            // 获取站点推演值
            $stationDeductionSql  = "SELECT * FROM `control_plan_from_bureau_station_details_hour` WHERE
 `region_id` = 53 AND `station_id` = ? AND `plan_number` = ? AND `tsinghua_plan_id` = ? AND `publish_time` = ? AND
 `predict_time` between ? AND ?";
            $stationDeductionData = Db::query($stationDeductionSql, array(
                $stationId, $programmeNumber, $planId, $publishTime, $controlStartTime, $controlEndTime));
            $deductionPollutant   = array_column($stationDeductionData, $pollutant);

            // 组合数据
            $dateArr = handleStationTime($dateRange);
            $result  = [
                "date" => $dateArr,
                "data" => [
                    roundStationData($deductionPollutant, $pollutant),
                    roundStationData($forecastPollutant, $pollutant),
                    roundStationData($realtimePollutant, $pollutant),
                ]
            ];

            return $result;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :获取站点管控跟踪数据
     * @param $paramArr
     * @return array
     * @throws \Exception
     * @author lichao   2019/6/29
     */
    public function getStationTrackTableData($paramArr)
    {
        try {
            $control          = new ControlPlan();
            $programmeNumber  = $paramArr['plan_number'];
            $planId           = $this->getPlanIdByPlanNumber($paramArr['plan_number'], '', true);
            $planData         = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
            $publishTime      = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
            $controlStartTime = $planData['control_start_time'];
            $controlEndTime   = $planData['control_end_time'];
            $stationList      = $control->getStationList(53, 1);
            $dateRange        = getDateFromRange($controlStartTime, $controlEndTime);
            $dayNum           = count($dateRange);

            // 站点预报值
            $stationForecastData = $control->getStationForecastData($stationList, $dayNum, $publishTime, $controlStartTime, $controlEndTime);
            // 站点推演值
            $stationDeductionData = $control->getStationDeductionData($stationList, $dayNum, $programmeNumber, $planId, $publishTime, $controlStartTime, $controlEndTime);

            // 获取站点实测值
            $stationRealtimeData = $control->getStationRealtimeData($controlStartTime, $controlEndTime);

            $aqi              = new AqiService();
            $newData          = array();
            $pollutantsKeyArr = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'aqi'
            ];
            $aqiKeyArr        = [
                'pm10', 'pm25', 'so2', 'no2', 'co', 'o3', 'o3_8h'
            ];

            foreach ($stationList as $station => $stationName) {
                $forecast_cp_arr  = array();
                $deduction_cp_arr = array();
                $realtime_cp_arr  = array();
                foreach ($aqiKeyArr as $pollutantVal) {
                    $pollutantKey = $pollutantVal . "_" . $station;
                    if ($pollutantVal == 'o3' || $pollutantVal == 'o3_8h') {
                        $forecast_cp_arr[$pollutantVal . '_average_max']  = $stationForecastData[$pollutantKey];
                        $deduction_cp_arr[$pollutantVal . '_average_max'] = $stationDeductionData[$pollutantKey];
                        // 实测数据
                        if (!empty($stationRealtimeData)) {
                            $realPollutantVal = $stationRealtimeData[$station][$pollutantVal];

                            $realtime_cp_arr[$pollutantVal . '_average_max'] = $realPollutantVal;
                        }
                    } else {
                        $forecast_cp_arr[$pollutantVal . '_average']  = $stationForecastData[$pollutantKey];
                        $deduction_cp_arr[$pollutantVal . '_average'] = $stationDeductionData[$pollutantKey];
                        // 实测数据
                        if (!empty($stationRealtimeData)) {
                            $realPollutantVal = $stationRealtimeData[$station][$pollutantVal];

                            $realtime_cp_arr[$pollutantVal . '_average'] = $realPollutantVal;
                        }
                    }
                }
                // 计算AQI
                $stationForecastAqi                      = $aqi->getAqi($forecast_cp_arr)['aqi'];
                $stationDeductionAqi                     = $aqi->getAqi($deduction_cp_arr)['aqi'];
                $stationForecastData['aqi_' . $station]  = $stationForecastAqi;
                $stationDeductionData['aqi_' . $station] = $stationDeductionAqi;
                // 实测值AQI
                if (!empty($stationRealtimeData)) {
                    $stationRealtimeAqi                   = $aqi->getAqi($realtime_cp_arr)['aqi'];
                    $stationRealtimeData[$station]['aqi'] = $stationRealtimeAqi;
                }

                foreach ($pollutantsKeyArr as $item) {
                    $pollutants   = $item == 'pm25' ? 'PM2_5' : strtoupper($item);
                    $pollutant    = $item == 'pm25' ? 'PM2.5' : strtoupper($item);
                    $pollutantKey = $item . "_" . $station;
                    if (isset($stationForecastData[$pollutantKey])) {
                        $forecastPollutantVal  = $stationForecastData[$pollutantKey];
                        $deductionPollutantVal = $stationDeductionData[$pollutantKey];
                        $improve               = $forecastPollutantVal - $deductionPollutantVal;
                        $forecastValue         = $control->roundStationValue($forecastPollutantVal, $item);
                        $deductionValue        = $control->roundStationValue($deductionPollutantVal, $item);
                        // 组合数组
                        $newData[$pollutants][$station]['station_id'] = $station;
                        $newData[$pollutants][$station]['site']       = $stationName;
                        $newData[$pollutants][$station]['pollutants'] = $pollutant;
                        $newData[$pollutants][$station]['forecast']   = $forecastValue;
                        $newData[$pollutants][$station]['deduction']  = $deductionValue;
                        $newData[$pollutants][$station]['improve']    = round($improve, 1);
                        // 站点实测值
                        if (!empty($stationRealtimeData)) {
                            foreach ($stationRealtimeData as $stationKey => $realtimeDatum) {
                                if ($stationKey == $station) {
                                    $realtimeValue = $control->roundStationValue($realtimeDatum[$item], $item);

                                    $newData[$pollutants][$station]['realtime'] = $realtimeValue;
                                }
                            }
                        } else {
                            $newData[$pollutants][$station]['realtime'] = '';
                        }
                    }
                }
            }

            $data = array();
            if (!empty($newData)) {
                foreach ($newData as $i => $newDatum) {
                    $data[$i] = array_values($newDatum);
                    // $dataSum  = array();
                    // foreach ($newDatum as $j => $item) {
                    //     if ($j != 0) {
                    //         array_push($dataSum, $item['improve']);
                    //     }
                    // }
                    // $data[$i . 'average'] = round(array_sum($dataSum) / 5, 1);
                }
            } else {
                return array([[], [], []]);
            }

            return $data;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :提交方案
     * @param $paramArr
     * @return int
     * @throws \Exception
     * @author lichao   2019/6/28
     */
    public function confirmPlanBeLaidUp($paramArr)
    {
        try {
            if ($paramArr['plan_name'] == '方案不成立') {
                $bureauPlanStatus = $this->updateConfirmPlan($paramArr['plan_number'], $paramArr['explain'], true);
            } else {
                $planId           = $this->getPlanIdByPlanNumber($paramArr['plan_number'], $paramArr['plan_name']);
                $bureauPlanStatus = $this->updateConfirmPlan($paramArr['plan_number'], $paramArr['explain'], false, $planId);
            }

            return $bureauPlanStatus;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :更新方案数据
     * @param $planNumber
     * @param $explain
     * @param bool $state
     * @param string $planId
     * @return int
     * @author lichao   2019/6/28
     */
    public function updateConfirmPlan($planNumber, $explain, $state = false, $planId = '')
    {
        if ($state) {
            $planSql          = "UPDATE `control_plan_from_tsinghua_plan` SET `confirm_scheme` = 2, `explain` = ?,
 `update_time` = ? WHERE `plan_number` = ?";
            $bureauPlanStatus = Db::execute($planSql, array($explain, time(), $planNumber));
        } else {
            $planOriginalSql    = "UPDATE `control_plan_from_tsinghua_plan` SET `confirm_scheme` = 0, `explain` = '',
 `update_time` = ? WHERE `plan_number` = ?";
            $planOriginalStatus = Db::execute($planOriginalSql, array(time(), $planNumber));
            $planSql            = "UPDATE `control_plan_from_tsinghua_plan` SET `confirm_scheme` = 1, `explain` = ?,
`update_time` = ? WHERE `plan_number` = ? AND `bureau_plan_id` = ?";
            $bureauPlanStatus   = Db::execute($planSql, array($explain, time(), $planNumber, $planId));
        }

        return $bureauPlanStatus;
    }

    /**
     * Notes :获取确认预案全部方案推演数据
     * @param $paramArr
     * @return array
     * @throws \MongoDB\Driver\Exception\Exception
     * @author lichao   2019/7/18
     */
    public function getPlanSummaryAll($paramArr)
    {
        /**
         * data: [{
         * plan: '1',
         * emission_SO2: '20',
         * emission_NO2: 25,
         * falling_PM2_5: 25,
         * falling_SO2: 25,
         * falling_NO2: 50,
         * forecast: 20,
         * improve: 40
         * },
         */
        try {
            $planNumber = $paramArr['plan_number'];
            // 工业目标减排量
            $industryData   = $this->getIndustryReduce($planNumber);
            $formula        = new FormulaService();
            $industryReduce = [];
            if ($industryData) {
                $dataOrigin    = $industryData['dataOrigin'];
                $dataTsingPlan = $industryData['dataTsingPlan'];
                //step3：得到目标排放量
                foreach ($dataTsingPlan as $k => $v) {
                    $industryReduce[$k]['SO2'] = $formula->targetEmission($dataOrigin['so2_emissions'], $v['tsinghua_emission_so2']);
                    $industryReduce[$k]['NO2'] = $formula->targetEmission($dataOrigin['no2_emissions'], $v['tsinghua_emission_no2']);
                }
            }
            $stationAveragePollutant = $this->getStationAveragePollutant($paramArr);    // 站点污染物平均下降浓度
            $stationAverageAqi       = $this->getStationAverageAqi($paramArr);          // 全市AQI减排后预报值
            $stationAverageImprove   = $this->getStationAverageDeduction($paramArr);      // 预案推演改善值

            // dump($stationAveragePollutant);
            // dump($stationAverageAqi);
            // dump($stationAverageImprove);
            $emissionDataArr = [
                "SO2" => "emission_SO2",
                "NO2" => "emission_NO2",
            ];
            $fallingDataArr  = [
                "PM2_5" => "falling_PM2_5",
                "SO2"   => "falling_SO2",
                "NO2"   => "falling_NO2",
            ];
            $date            = array();
            $dateArr         = array('方案一', '方案二', '方案三');
            $result          = array();
            foreach ($stationAveragePollutant as $key => $value) {
                // 趋势图数据
                array_push($date, $dateArr[$key]);
                // 表格数据
                $result['table_data'][$key]['plan'] = $key + 1;     // 方案id
                foreach ($industryReduce as $index => $item) {
                    if ($key == $index) {
                        foreach ($item as $k => $val) {
                            $result['table_data'][$key][$emissionDataArr[$k]]           = $val;    // 工业减排量
                            $result['echart_data']['industry_reduce']['date']           = $date;
                            $result['echart_data']['industry_reduce']['data'][$k][$key] = $val;
                        }
                    }
                }
                foreach ($value as $index => $item) {
                    $result['table_data'][$key][$fallingDataArr[$index]] = $item;    // 站点污染物下降浓度
                    // 下降浓度
                    $result['echart_data']['nonddu_data']['date']               = $date;
                    $result['echart_data']['nonddu_data']['data'][$index][$key] = $item;
                }
                $result['table_data'][$key]['forecast'] = $stationAverageAqi[$key];         // AQI预报
                $result['table_data'][$key]['improve']  = $stationAverageImprove[$key];     // 推演改善值
            }

            // 趋势图数据
            // AQI
            $result['echart_data']['aqi_data']['date']   = $date;
            $result['echart_data']['aqi_data']['data'][] = array_values($stationAverageAqi);
            // 改善值
            $result['echart_data']['improve']['date']   = $date;
            $result['echart_data']['improve']['data'][] = array_values($stationAverageImprove);

            // dump($result);

            return $result;
        } catch (\Exception $e) {
            throw $e;
        }
    }

    /**
     * Notes :获取工业目标排放量
     * @param $planNumber
     * @return bool
     * @throws \MongoDB\Driver\Exception\Exception
     * @author lichao   2019/7/17
     */
    public function getIndustryReduce($planNumber)
    {
        try {
            $controlEmission = new ControlEmissionService();
            //step1：管控期间原始排放量
            $data['dataOrigin'] = $controlEmission->getTsinghuaTimesOriginCompanyEmissionTotalCompanyHourAvg($planNumber, 't');
            //step2：清华方案排放量
            $tsinghuaEmission      = new TsinghuaEmissionService();
            $data['dataTsingPlan'] = $tsinghuaEmission->getTsinghuaPlanTotalEmissionHourAvg($planNumber, 't');

            return $data;
        } catch (\Exception $e) {
            // todo 接口错误 异常先不抛出，继续执行其他方法 lichao
            // exception($e->getMessage());
            return false;
        }
    }

    /**
     * Notes :获取推演改善值
     * @param $paramArr
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/6/27
     */
    public function getStationAverageDeduction($paramArr)
    {
        $aqiDeductionArr = $this->getStationAverageAqi($paramArr);
        $aqiForecast     = $this->getStationForecastAverageAqi($paramArr);

        $aqiArr = array();
        foreach ($aqiDeductionArr as $key => $item) {
            if ($item == '-') {
                $aqiArr[$key] = '-';
            } else {
                $aqiArr[$key] = $aqiForecast - $item;
            }
        }

        return $aqiArr;
    }

    /**
     * Notes :获取站点污染物平均下降浓度
     * @param $paramArr
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/6/27
     */
    public function getStationAveragePollutant($paramArr)
    {
        $control           = new ControlPlan();
        $planData          = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
        $planIds           = $this->getPlanIdByPlanNumber($paramArr['plan_number']);
        $planNumber        = $paramArr['plan_number'];
        $publishTime       = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
        $startTime         = $planData['control_start_time'];
        $endTime           = $planData['control_end_time'];
        $dateRange         = getDateFromRange($startTime, $endTime);
        $dayNum            = count($dateRange);
        $cityDeductionData = array();

        $cityForecastData = $this->getForecastData($startTime, $endTime, $publishTime, $dayNum);
        foreach ($planIds as $k => $planId) {
            $cityDeductionData[$k] = $this->getDeductionData($startTime, $endTime, $publishTime, $planNumber, $planId['bureau_plan_id'], $dayNum);
        }

        $pollutantsArr = array('pm25', 'so2', 'no2');
        $result        = array();
        foreach ($cityForecastData as $key => $cityForecastDatum) {
            foreach ($cityDeductionData as $index => $cityDeductionDatum) {
                if (array_key_exists($key, $cityDeductionDatum)) {
                    if (in_array($key, $pollutantsArr)) {   // 筛选3个污染物
                        $pollutant = $key == 'pm25' ? 'PM2_5' : strtoupper($key);
                        $retain    = $key == "co" ? 1 : 0;
                        if ($cityDeductionDatum[$key] == null) {
                            $avgPollutant = '-';
                        } else {
                            $avgPollutant = round($cityForecastDatum - $cityDeductionDatum[$key], $retain);
                        }
                        $result[$index][$pollutant] = $avgPollutant;
                    }
                }
            }
        }

        return $result;
    }

    /**
     * Notes :获取全市减排后AQI均值
     * @param $paramArr
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/6/27
     */
    public function getStationAverageAqi($paramArr)
    {
        $control     = new ControlPlan();
        $aqi         = new AqiService();
        $planNum     = $paramArr['plan_number'];
        $planIds     = $this->getPlanIdByPlanNumber($paramArr['plan_number']);
        $planData    = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
        $publishTime = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
        $startTime   = $planData['control_start_time'];
        $endTime     = $planData['control_end_time'];
        $dateRange   = getDateFromRange($startTime, $endTime);
        $dayNum      = count($dateRange);
        $aqiArr      = array();
        foreach ($planIds as $key => $planId) {
            $aqiArr[$key] = $this->getDeductionAqi($aqi, $startTime, $endTime, $publishTime, $planNum, $planId['bureau_plan_id'], $dayNum);
        }

        return $aqiArr;
    }

    /**
     * Notes :获取预报值AQI
     * @param $paramArr
     * @return AqiService
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @author lichao   2019/6/27
     */
    public function getStationForecastAverageAqi($paramArr)
    {
        $control     = new ControlPlan();
        $aqi         = new AqiService();
        $planData    = $control->getControlTime($paramArr['plan_number'], $paramArr['plan_type']);
        $publishTime = date("Y-m-d 00:00:00", strtotime($planData['control_start_time']) - 24 * 3600);
        $startTime   = $planData['control_start_time'];
        $endTime     = $planData['control_end_time'];
        $dateRange   = getDateFromRange($startTime, $endTime);
        $dayNum      = count($dateRange);
        $aqiArr      = $this->getForecastAqi($aqi, $startTime, $endTime, $publishTime, $dayNum);

        return $aqiArr;
    }

    /**
     * Notes :计算预报值AQI
     * @param AqiService $aqi
     * @param $startTime
     * @param $endTime
     * @param $publishTime
     * @return AqiService
     * @author lichao   2019/6/27
     */
    public function getForecastAqi(AqiService $aqi, $startTime, $endTime, $publishTime, $dayNum)
    {
        $forecastData = $this->getForecastData($startTime, $endTime, $publishTime, $dayNum);
        $cpArr        = [
            'pm10_average'      => $forecastData['pm10'],
            'pm25_average'      => $forecastData['pm25'],
            'so2_average'       => $forecastData['so2'],
            'no2_average'       => $forecastData['no2'],
            'co_average'        => $forecastData['co'],
            'o3_average_max'    => $forecastData['o3'],
            'o3_8h_average_max' => $forecastData['o3_8hour'],
        ];
        $aqi          = $aqi->getAqi($cpArr, false, false, false)['aqi'];

        return $aqi;
    }

    /**
     * Notes :获取全市预报值
     * @param $controlStartTime
     * @param $controlEndTime
     * @param $publishTime
     * @return mixed
     * @author lichao   2019/6/27
     */
    public function getForecastData($controlStartTime, $controlEndTime, $publishTime, $dayNum)
    {
        $cityForecastSql  = "SELECT SUM(pm25) / " . $dayNum . " as pm25,SUM(pm10) / " . $dayNum .
            " as pm10,SUM(so2) / " . $dayNum . " as so2, SUM(no2) / " . $dayNum . " as no2,SUM(co) / " .
            $dayNum . " as co,SUM(o3) / " . $dayNum . " as o3,SUM(o3_8hour) / " . $dayNum . " as o3_8hour
 FROM `air_quality_station_aqi_forecast_day` WHERE predict_time BETWEEN ? AND ? AND
  publish_time = ? AND station_id = ? AND region_id = 53";
        $cityForecastData = Db::query($cityForecastSql, array(
            $controlStartTime, $controlEndTime, $publishTime, 0));

        return $cityForecastData[0];
    }

    /**
     * Notes :获取全市推演3天AQI平均值
     * @param AqiService $aqi
     * @param $startTime
     * @param $endTime
     * @param $publishTime
     * @param $planNumber
     * @param $planId
     * @param $dayNum
     * @return AqiService
     * @author lichao   2019/7/22
     */
    public function getDeductionAqi(AqiService $aqi, $startTime, $endTime, $publishTime, $planNumber, $planId, $dayNum)
    {
        $deductionData = $this->getDeductionData($startTime, $endTime, $publishTime, $planNumber, $planId, $dayNum);
        if (array_sum($deductionData) == null) {
            $aqi = '-';
        } else {
            $cpArr         = [
                'pm10_average'      => $deductionData['pm25'],
                'pm25_average'      => $deductionData['pm10'],
                'so2_average'       => $deductionData['so2'],
                'no2_average'       => $deductionData['no2'],
                'co_average'        => $deductionData['co'],
                'o3_average_max'    => $deductionData['o3'],
                'o3_8h_average_max' => $deductionData['o3_8hour'],
            ];
            $aqi           = $aqi->getAqi($cpArr, false, false, false)['aqi'];
        }

        return $aqi;
    }

    /**
     * Notes :获取3天推演数据
     * @param $controlStartTime
     * @param $controlEndTime
     * @param $publishTime
     * @param $planNumber
     * @param $planId
     * @param $dayNum
     * @return mixed
     * @author lichao   2019/7/22
     */
    public function getDeductionData($controlStartTime, $controlEndTime, $publishTime, $planNumber, $planId, $dayNum)
    {
        $cityDeductionSql  = "SELECT SUM(pm25) / " . $dayNum . " as pm25,SUM(pm10) / " . $dayNum .
            " as pm10,SUM(so2) / " . $dayNum . " as so2, SUM(no2) / " . $dayNum . " as no2,SUM(co) / " .
            $dayNum . " as co,SUM(o3) / " . $dayNum . " as o3,SUM(o3_8hour) / " . $dayNum . " as o3_8hour
 FROM `control_plan_from_bureau_station_details_day` WHERE predict_time BETWEEN ? AND ? AND
  publish_time = ? AND plan_number = ? AND tsinghua_plan_id = ? AND station_id = ? AND region_id = 53";
        $cityDeductionData = Db::query($cityDeductionSql, array(
            $controlStartTime, $controlEndTime, $publishTime, $planNumber, $planId, 0));

        return $cityDeductionData[0];
    }

    /**
     * Notes :根据预案编号获取方案id列表或单个方案id
     * @param $planNumber
     * @param string $planName
     * @param bool $confirm
     * @return mixed
     * @throws \Exception
     * @author lichao   2019/7/22
     */
    public function getPlanIdByPlanNumber($planNumber, $planName = '', $confirm = false)
    {
        $bureauPlanSql = "SELECT `bureau_plan_id` FROM `control_plan_from_tsinghua_plan` WHERE `plan_number` = ?";
        if ($planName != '') {
            $bureauPlanSql  .= " AND `name`= ?";
            $bureauPlanData = Db::query($bureauPlanSql, array($planNumber, $planName));
            if (empty($bureauPlanData)) {
                throw new \Exception('方案不存在');
            }

            return $bureauPlanData[0]['bureau_plan_id'];
        } elseif ($confirm) {
            $bureauPlanSql  .= " AND `confirm_scheme`= 1";
            $bureauPlanData = Db::query($bureauPlanSql, array($planNumber));
            if (empty($bureauPlanData)) {
                throw new \Exception('方案不存在');
            }

            return $bureauPlanData[0]['bureau_plan_id'];
        } else {
            $bureauPlanData = Db::query($bureauPlanSql, array($planNumber));
            return $bureauPlanData;
        }
    }

}
